package com.javaweb.service.impl;

import com.javaweb.common.BusinessConstants;
import com.javaweb.dao.ArticleDao;
import com.javaweb.dao.UserDao;
import com.javaweb.model.Article;
import com.javaweb.service.ArticleService;
import com.javaweb.service.dto.ArticleConditionDto;
import com.javaweb.service.dto.ArticleUpdateDto;
import com.javaweb.service.dto.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private ArticleDao articleDao;

    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            timeout = -1,
            readOnly = false,
            rollbackFor = Throwable.class
    )
    @Override
    public int publishArticle(String userId, String articleId) {
        Integer ret = articleDao.updateStatus(Integer.valueOf(articleId), BusinessConstants.ARTICLE_PUBLISHED);

        if (ret > 0) {
            ret = userDao.updateScore(Integer.valueOf(userId), BusinessConstants.ARTICLE_SCORE);
        } else {
            log.error("publish article: update status failed for articleId {}", articleId);
            return 0;
        }

        log.info("Article published successfully: articleId {}", articleId);
        return ret;
    }

    @Override
    public PageResult<Article> queryByArticleCondition(ArticleConditionDto articleCond, Integer pageNum, Integer pageSize) {
        // Implement pagination logic here
        List<Article> articles = articleDao.selectByUserId(Integer.valueOf(articleCond.getId()));

        // Optionally filter by other conditions if provided
        // Example: filter by keyword, category, etc.
        List<Article> filteredArticles = articles.stream()
                .filter(article -> articleCond.getKeyword() == null || article.getTitle().contains(articleCond.getKeyword()))
                .collect(Collectors.toList());

        // Handle pagination
        int total = filteredArticles.size();
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, total);
        List<Article> pagedArticles = filteredArticles.subList(start, end);

        return new PageResult<>(pagedArticles, pageNum, pageSize, total);
    }

    @Override
    public Article queryById(String articleId) {
        Article article = articleDao.selectByUserId(Integer.valueOf(articleId)).stream().findFirst().orElse(null);

        if (article == null) {
            log.warn("Article with id {} not found.", articleId);
        }
        return article;
    }

    @Override
    public Article insertArticle(Article article) {
        // Set creation and update time
        article.setCreateTime(new Date());
        article.setUpdateTime(new Date());

        int rowsAffected = articleDao.insert(article);
        if (rowsAffected > 0) {
            log.info("Inserted article successfully: {}", article);
            return article; // Return the article with the new ID
        } else {
            log.error("Failed to insert article: {}", article);
            return null; // Optionally throw an exception
        }
    }

    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            timeout = -1,
            readOnly = false,
            rollbackFor = Throwable.class
    )
    @Override
    public int publishArticlesByBatch(String[] articleIds, String userId) {
        int totalUpdated = 0;
        for (String articleId : articleIds) {
            int result = publishArticle(userId, articleId);
            if (result == 1) {
                totalUpdated++;
            }
        }
        return totalUpdated;
    }

    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            timeout = -1,
            readOnly = false,
            rollbackFor = Throwable.class
    )
    @Override
    public int updateArticle(ArticleUpdateDto articleVo) {
        int rowsAffected = 0;

        if (articleVo.getTitle() != null) {
            rowsAffected += articleDao.updateTitle(Integer.valueOf(articleVo.getId()), articleVo.getTitle());
        }
        if (articleVo.getContent() != null) {
            rowsAffected += articleDao.updateContent(Integer.valueOf(articleVo.getId()), articleVo.getContent());
        }

        if (articleVo.getDescription() != null) {
            // Assuming a method exists for updating the description
            // rowsAffected += articleDao.updateDescription(Integer.valueOf(articleVo.getId()), articleVo.getDescription());
        }

        // Handle more fields as necessary

        if (rowsAffected > 0) {
            log.info("Updated article successfully: id {}", articleVo.getId());
            return 1; // Successfully updated
        } else {
            log.error("Failed to update article: id {}", articleVo.getId());
            return 0; // Update failed
        }
    }

    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            timeout = -1,
            readOnly = false,
            rollbackFor = Throwable.class
    )
    @Override
    public int removeArticle(String articleId, String userId) {
        int rowsAffected = articleDao.deleteById(Integer.valueOf(articleId));
        if (rowsAffected > 0) {
            userDao.updateScore(Integer.valueOf(userId), -BusinessConstants.ARTICLE_SCORE); // Deduct score for article removal
            log.info("Removed article successfully: id {}", articleId);
            return 1; // Successfully removed
        } else {
            log.error("Failed to remove article with id: {}", articleId);
            return 0; // Removal failed
        }
    }
}
